﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

using SMBL.Core;
using SMBL.Interface.Database;
using SMBL.Interface.Document;
using SMBL.ADBS.Providers;
using SMBL.ADBS;
using SMBL.AFS;
using SMBL.AFS.Providers;

namespace SMBL.Control
{
    /// <summary>
    /// Control Center
    /// Used to process all exceptions occurred in the process
    /// @Author: Push
    /// </summary>
    public class ControlCenter
    {
        /////////////////////////////////////////////////////////////////////////
        // Parameter
        /////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Global Operation and Provider List
        /// @Author: Push
        /// </summary>
        private static Hashtable gOpProviderList;

        /// <summary>
        /// Global Operation and Document List
        /// @Author: Push
        /// </summary>
        private static Hashtable gOpDocList;

        /////////////////////////////////////////////////////////////////////////
        // Global API
        /////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Register the operation
        /// Require an IProvider and add both the operation and the provider to a hashtable
        /// @Author: Push
        /// </summary>
        /// <param name="TheOperation"></param>
        /// <returns></returns>
        public static Boolean Register(SMBL.Interface.Operation.IOperation TheOperation)
        {
            // Initialize the global operation provider list
            if (gOpProviderList == null) gOpProviderList = new Hashtable();
            try
            {
                // Require for an IProvider
                IDBProvider tmpProvider = ConnectionControl.GetConnection(TheOperation.GetBindString());
                tmpProvider.Start();
                TheOperation.SetProcessor((IDBProcessor)tmpProvider);

                // Registe to the List
                gOpProviderList.Add(TheOperation, tmpProvider);
                return true;
            }
            catch (Exception exp)
            {
                TheOperation.SetLastErrorId(ErrorSystem.CatchError(exp));
                return false;
            }
        }

        /// <summary>
        /// Register the document operation
        /// @Author: Push
        /// </summary>
        /// <param name="TheOperation"></param>
        /// <returns></returns>
        public static Boolean DocRegister(SMBL.Interface.Operation.IOperation TheOperation)
        {
            // Initialize the global operation document list
            if (gOpDocList == null) gOpDocList = new Hashtable();
            try
            {
                // Require for an IDocProvider
                IDocProvider tmpProvider = DocumentPool.GetDocument(TheOperation.GetBindString());
                tmpProvider.Start();

                // Set the processor
                TheOperation.SetProcessor((IDocProcessor)tmpProvider);

                // Register
                gOpDocList.Add(TheOperation, tmpProvider);
                return true;
            }
            catch (Exception exp)
            {
                TheOperation.SetLastErrorId(ErrorSystem.CatchError(exp));
                return false;
            }
        }

        /// <summary>
        /// UnRegister the Operation with the Processor
        /// @Author: Push
        /// </summary>
        /// <param name="TheOperation"></param>
        /// <returns></returns>
        public static Boolean UnRegister(SMBL.Interface.Operation.IOperation TheOperation)
        {
            if (null == TheOperation || !gOpProviderList.ContainsKey(TheOperation))
            {
                // The operation hasn't registed yeat.
                return false;
            }

            IDBProvider tmpProvider = (IDBProvider)gOpProviderList[TheOperation];

            // Release the connection
            ConnectionControl.ReleaseConnection(TheOperation.GetBindString(), tmpProvider);

            // Remove the information
            TheOperation.ReleaseProcessor();
            gOpProviderList.Remove(TheOperation);

            return true;
        }

        /// <summary>
        /// UnRegister the document provider
        /// @Author: Push
        /// </summary>
        /// <param name="TheOperation"></param>
        /// <returns></returns>
        public static Boolean DocUnRegister(SMBL.Interface.Operation.IOperation TheOperation)
        {
            if (null == TheOperation || !gOpDocList.ContainsKey(TheOperation))
            {
                // No such operation
                return false;
            }

            // Release the provider
            IDocProvider tmpProvider = (IDocProvider)gOpDocList[TheOperation];
            tmpProvider.End();
            DocumentPool.ReleaseDocument(tmpProvider);

            // Remove the information
            TheOperation.ReleaseProcessor();
            gOpDocList.Remove(TheOperation);

            return true;
        }

        /// <summary>
        /// Invoke the processDelegate method to do the process
        /// Any exception will be caught by the Control Center
        /// @Author: Push
        /// </summary>
        /// <param name="TheOperation"></param>
        /// <returns></returns>
        public static Boolean DoUnderControl(SMBL.Interface.Operation.IOperation TheOperation)
        {
            // Null reference check
            if (TheOperation == null) return false;

            // Invoke the operation's method to do everything
            try
            {
                TheOperation.processDelegate();
                return true;
            }
            catch (Exception exp)
            {
                TheOperation.SetLastErrorId(ErrorSystem.CatchError(exp));
                return false;
            }
        }
    }
}
